package yuchen.androidocr.imageUtil;

import android.graphics.Bitmap;
import android.graphics.Color;

import java.util.ArrayList;

/**
 * Created by yuchen on 5/15/16.
 */
public class ImageThreshold {

    public ArrayList OTSUAlgorithm(int[] src,int w,int h) {

        int width = w;
        int height = h;

        ArrayList returnResult = new ArrayList();
        double[] m_pFstdHistogram = new double[256];//表示灰度值的分布点概率
        double[] m_pFGrayAccu = new double[256]; //其中每一个值等于m_pFstdHistogram中从0到当前下标值的和
        double[] m_pFGrayAve = new double[256]; //其中每一值等于m_pFstdHistogram中从0到当前指定下标值*对应的下标之和
        double m_pAverage = 0; //值为m_pFstdHistogram【256】中每一点的分布概率*当前下标之和
        int[] m_pHistogram = new int[256]; //灰度直方图
        int i, j;
        double temp = 0, fMax = 0; //定义一个临时变量和一个最大类间方差的值
        int nThresh = 0; //最优阀值
        //初始化各项参数
        for (i = 0; i < 256; i++) {
            m_pFstdHistogram[i] = 0;
            m_pFGrayAccu[i] = 0;
            m_pFGrayAve[i] = 0;
            m_pHistogram[i] = 0;
        }
        //获取图像信息

        //获取图像的像素
        int pixels[] = new int[width * height];
        pixels = src;
        //src.getPixels(pixels,0, width, 0, 0,width,height);// 读进的图像的RGB值

        for (i = 0; i < pixels.length; i++) {
            //获取r的像素值，因为灰度图像，r=g=b，所以取第一个即可
            int r = Color.red(pixels[i]);
            m_pHistogram[r] ++;
        }

        //下面计算每一个灰度点在图像中出现的概率
        double size = width * height;
        for (i = 0; i < 256; i++) {
            m_pFstdHistogram[i] = m_pHistogram[i] / size;
        }
        //下面开始计算m_pFGrayAccu和m_pFGrayAve和m_pAverage的值
        for (i = 0; i < 256; i++) {
            for (j = 0; j <= i; j++) {
                //计算m_pFGaryAccu[256]
                m_pFGrayAccu[i] += m_pFstdHistogram[j];
                //计算m_pFGrayAve[256]
                m_pFGrayAve[i] += j * m_pFstdHistogram[j];
            }
            //计算平均值
            m_pAverage += i * m_pFstdHistogram[i];
        }
        //alert("m_pFstdHistogram:"+m_pFstdHistogram);
        //下面开始就算OSTU的值，从0-255个值中分别计算ostu并寻找出最大值作为分割阀值
        for (i = 0; i < 256; i++) {
            temp = (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i]) * (m_pAverage * m_pFGrayAccu[i] - m_pFGrayAve[i]) / (m_pFGrayAccu[i] * (1 - m_pFGrayAccu[i]));
            if (temp > fMax) {
                fMax = temp;
                nThresh = i;
            }
        }
        //mat为矩阵，存黑色为1，白色为0，为数字识别服务
        ArrayList mat = new ArrayList();
        ArrayList countX = new ArrayList();
        //黑白化之后进行数字黑背景区分，0，255两数，如果数字出现次数多就是背景，否则就是数字
        int blackLength = 0;


        int imageData[] = new int[width*height];
        //src.getPixels(imageData,0, width, 0, 0,width,height);// 读进的图像的RGB值
        imageData = src;
        //下面执行二值化过程
        for (i = 0; i < width; i++) {
            for (j = 0; j < height; j++) {
                int ids = (i + j * width);
                //取得像素的R分量的值
                int r = Color.red(imageData[ids]);
                //与阀值进行比较，如果小于阀值，那么将改点置为0，否则置为255
                //var gray = r > nThresh ? 255 : 0;
                int gray;
                if (r > nThresh) { //255白色
                    gray = 255;
                } else { //0黑色
                    gray = 0;
                    blackLength++;
                }
                int rgb =  Color.rgb(gray,gray,gray);
                imageData[ids] = rgb;
                if (i < 2 || j < 2 || i > (width - 2) || j > (height - 2)) {
                    imageData[ids] =  Color.rgb(255,255,255);
                }
            }
        }

        //显示二值化图像
        returnResult.add(imageData);
        returnResult.add(countX);
        returnResult.add(mat);
        return returnResult;
    }

}
